{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "socSJe925zFv",
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "#  The Basic Tools of the Deep Life Sciences\n",
    "Welcome to DeepChem's introductory tutorial for the deep life sciences. This series of notebooks is a step-by-step guide for you to get to know the new tools and techniques needed to do deep learning for the life sciences. We'll start from the basics, assuming that you're new to machine learning and the life sciences, and build up a repertoire of tools and techniques that you can use to do meaningful work in the life sciences.\n",
    "\n",
    "**Scope:** This tutorial will encompass both the machine learning and data handling needed to build systems for the deep life sciences.\n",
    "\n",
    "## Colab\n",
    "\n",
    "This tutorial and the rest in the sequences are designed to be done in Google colab. If you'd like to open this notebook in colab, you can use the following link.\n",
    "\n",
    "[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/deepchem/deepchem/blob/master/examples/tutorials/The_Basic_Tools_of_the_Deep_Life_Sciences.ipynb)\n",
    "\n",
    "\n",
    "## Why do the DeepChem Tutorial?\n",
    "\n",
    "**1) Career Advancement:** Applying AI in the life sciences is a booming\n",
    "industry at present. There are a host of newly funded startups and initiatives\n",
    "at large pharmaceutical and biotech companies centered around AI. Learning and\n",
    "mastering DeepChem will bring you to the forefront of this field and will\n",
    "prepare you to enter a career in this field.\n",
    "\n",
    "**2) Humanitarian Considerations:** Disease is the oldest cause of human\n",
    "suffering. From the dawn of human civilization, humans have suffered from pathogens,\n",
    "cancers, and neurological conditions. One of the greatest achievements of\n",
    "the last few centuries has been the development of effective treatments for\n",
    "many diseases. By mastering the skills in this tutorial, you will be able to\n",
    "stand on the shoulders of the giants of the past to help develop new\n",
    "medicine.\n",
    "\n",
    "**3) Lowering the Cost of Medicine:** The art of developing new medicine is\n",
    "currently an elite skill that can only be practiced by a small core of expert\n",
    "practitioners. By enabling the growth of open source tools for drug discovery,\n",
    "you can help democratize these skills and open up drug discovery to more\n",
    "competition. Increased competition can help drive down the cost of medicine.\n",
    "\n",
    "## Getting Extra Credit\n",
    "If you're excited about DeepChem and want to get more involved, there are some things that you can do right now:\n",
    "\n",
    "* Star DeepChem on GitHub! - https://github.com/deepchem/deepchem\n",
    "* Join the DeepChem forums and introduce yourself! - https://forum.deepchem.io\n",
    "* Say hi on the DeepChem gitter - https://gitter.im/deepchem/Lobby\n",
    "* Make a YouTube video teaching the contents of this notebook.\n",
    "\n",
    "\n",
    "## Prerequisites\n",
    "\n",
    "This tutorial sequence will assume some basic familiarity with the Python data science ecosystem. We will assume that you have familiarity with libraries such as Numpy, Pandas, and TensorFlow. We'll provide some brief refreshers on basics through the tutorial so don't worry if you're not an expert.\n",
    "\n",
    "## Setup\n",
    "\n",
    "The first step is to get DeepChem up and running. We recommend using Google Colab to work through this tutorial series. You'll also need to run the following commands to get DeepChem installed on your colab notebook. We are going to use a model based on tensorflow, because of that we've added [tensorflow] to the pip install command to ensure the necessary dependencies are also installed"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "CMWAv-Z46nCc",
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "!pip install --pre deepchem[tensorflow]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Installing tf_keras ensures the availability of legacy optimizers."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pip install tf_keras"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The os module is imported to access and modify environment variables in Python, allowing the configuration of TensorFlow to use tf_keras for legacy optimizer support."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "os.environ['TF_USE_LEGACY_KERAS'] = 'True'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "Jk47QTZ95zF-"
   },
   "source": [
    "You can of course run this tutorial locally if you prefer. In this case, don't run the above cell since it will download and install Anaconda on your local machine. In either case, we can now import the `deepchem` package to play with."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 35
    },
    "id": "PDiY03h35zF_",
    "outputId": "e3b7af38-f298-4161-db16-afbd3d4078c9"
   },
   "outputs": [
    {
     "data": {
      "application/vnd.google.colaboratory.intrinsic+json": {
       "type": "string"
      },
      "text/plain": [
       "'2.5.0.dev'"
      ]
     },
     "execution_count": 3,
     "metadata": {
      "tags": []
     },
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import deepchem as dc\n",
    "dc.__version__"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "B0u7qIZd5zGG"
   },
   "source": [
    "# Training a Model with DeepChem: A First Example\n",
    "\n",
    "Deep learning can be used to solve many sorts of problems, but the basic workflow is usually the same.  Here are the typical steps you follow.\n",
    "\n",
    "1. Select the data set you will train your model on (or create a new data set if there isn't an existing suitable one).\n",
    "2. Create the model.\n",
    "3. Train the model on the data.\n",
    "4. Evaluate the model on an independent test set to see how well it works.\n",
    "5. Use the model to make predictions about new data.\n",
    "\n",
    "With DeepChem, each of these steps can be as little as one or two lines of Python code.  In this tutorial we will walk through a basic example showing the complete workflow to solve a real world scientific problem.\n",
    "\n",
    "The problem we will solve is predicting the solubility of small molecules given their chemical formulas.  This is a very important property in drug development: if a proposed drug isn't soluble enough, you probably won't be able to get enough into the patient's bloodstream to have a therapeutic effect.  The first thing we need is a data set of measured solubilities for real molecules.  One of the core components of DeepChem is MoleculeNet, a diverse collection of chemical and molecular data sets.  For this tutorial, we can use the Delaney solubility data set. The property of solubility in this data set is reported in log(solubility) where solubility is measured in moles/liter."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "saTaOpXY5zGI"
   },
   "outputs": [],
   "source": [
    "tasks, datasets, transformers = dc.molnet.load_delaney(featurizer='GraphConv')\n",
    "train_dataset, valid_dataset, test_dataset = datasets"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "F922OPtL5zGM"
   },
   "source": [
    "I won't say too much about this code right now.  We will see many similar examples in later tutorials.  There are two details I do want to draw your attention to.  First, notice the `featurizer` argument passed to the `load_delaney()` function.  Molecules can be represented in many ways.  We therefore tell it which representation we want to use, or in more technical language, how to \"featurize\" the data.  Second, notice that we actually get three different data sets: a training set, a validation set, and a test set.  Each of these serves a different function in the standard deep learning workflow.\n",
    "\n",
    "Now that we have our data, the next step is to create a model.  We will use a particular kind of model called a \"graph convolutional network\", or \"graphconv\" for short."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "YEDcUsz35zGO"
   },
   "outputs": [],
   "source": [
    "model = dc.models.GraphConvModel(n_tasks=1, mode='regression', dropout=0.2,batch_normalize=False)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "E8UCFrrN5zGf"
   },
   "source": [
    "Here again I will not say much about the code.  Later tutorials will give lots more information about `GraphConvModel`, as well as other types of models provided by DeepChem.\n",
    "\n",
    "We now need to train the model on the data set.  We simply give it the data set and tell it how many epochs of training to perform (that is, how many complete passes through the data to make)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "e5K3rdGV5zGg"
   },
   "outputs": [],
   "source": [
    "model.fit(train_dataset, nb_epoch=100)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "_Zcd7jTd5zGr"
   },
   "source": [
    "If everything has gone well, we should now have a fully trained model!  But do we?  To find out, we must evaluate the model on the test set.  We do that by selecting an evaluation metric and calling `evaluate()` on the model.  For this example, let's use the Pearson correlation, also known as r<sup>2</sup>, as our metric.  We can evaluate it on both the training set and test set."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "LJc90fs_5zGs",
    "outputId": "770a8b76-1a7c-48a1-952e-1ae0343541c4"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Training set score: {'pearson_r2_score': 0.9323622956442351}\n",
      "Test set score: {'pearson_r2_score': 0.6898768897014962}\n"
     ]
    }
   ],
   "source": [
    "metric = dc.metrics.Metric(dc.metrics.pearson_r2_score)\n",
    "print(\"Training set score:\", model.evaluate(train_dataset, [metric], transformers))\n",
    "print(\"Test set score:\", model.evaluate(test_dataset, [metric], transformers))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "aQa88cbj5zGw"
   },
   "source": [
    "Notice that it has a higher score on the training set than the test set.  Models usually perform better on the particular data they were trained on than they do on similar but independent data.  This is called \"overfitting\", and it is the reason it is essential to evaluate your model on an independent test set.\n",
    "\n",
    "Our model still has quite respectable performance on the test set.  For comparison, a model that produced totally random outputs would have a correlation of 0, while one that made perfect predictions would have a correlation of 1.  Our model does quite well, so now we can use it to make predictions about other molecules we care about.\n",
    "\n",
    "Since this is just a tutorial and we don't have any other molecules we specifically want to predict, let's just use the first ten molecules from the test set.  For each one we print out the chemical structure (represented as a SMILES string) and the predicted log(solubility). To put these predictions in \n",
    "context, we print out the log(solubility) values from the test set as well."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "HSVqeYox5zGx",
    "outputId": "f2218dfc-e100-4950-9b09-5ff0be493cfa"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[-1.8629359] [-1.60114461] c1cc2ccc3cccc4ccc(c1)c2c34\n",
      "[0.6617248] [0.20848251] Cc1cc(=O)[nH]c(=S)[nH]1\n",
      "[-0.5705674] [-0.01602738] Oc1ccc(cc1)C2(OC(=O)c3ccccc23)c4ccc(O)cc4 \n",
      "[-2.0929456] [-2.82191713] c1ccc2c(c1)cc3ccc4cccc5ccc2c3c45\n",
      "[-1.4962314] [-0.52891635] C1=Cc2cccc3cccc1c23\n",
      "[1.8620405] [1.10168349] CC1CO1\n",
      "[-0.5858227] [-0.88987406] CCN2c1ccccc1N(C)C(=S)c3cccnc23 \n",
      "[-0.9799993] [-0.52649706] CC12CCC3C(CCc4cc(O)ccc34)C2CCC1=O\n",
      "[-1.0176951] [-0.76358725] Cn2cc(c1ccccc1)c(=O)c(c2)c3cccc(c3)C(F)(F)F\n",
      "[0.05622783] [-0.64020358] ClC(Cl)(Cl)C(NC=O)N1C=CN(C=C1)C(NC=O)C(Cl)(Cl)Cl \n"
     ]
    }
   ],
   "source": [
    "solubilities = model.predict_on_batch(test_dataset.X[:10])\n",
    "for molecule, solubility, test_solubility in zip(test_dataset.ids, solubilities, test_dataset.y):\n",
    "    print(solubility, test_solubility, molecule)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "MhZxVoVs5zMa"
   },
   "source": [
    "# Congratulations! Time to join the Community!\n",
    "\n",
    "Congratulations on completing this tutorial notebook! If you enjoyed working through the tutorial, and want to continue working with DeepChem, we encourage you to finish the rest of the tutorials in this series. You can also help the DeepChem community in the following ways:\n",
    "\n",
    "## Star DeepChem on [GitHub](https://github.com/deepchem/deepchem)\n",
    "This helps build awareness of the DeepChem project and the tools for open source drug discovery that we're trying to build.\n",
    "\n",
    "## Join the DeepChem Gitter\n",
    "The DeepChem [Gitter](https://gitter.im/deepchem/Lobby) hosts a number of scientists, developers, and enthusiasts interested in deep learning for the life sciences. Join the conversation!"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "pOBd6-YdQSvF"
   },
   "source": [
    "## Citing This Tutorial\n",
    "If you found this tutorial useful please consider citing it using the provided BibTeX. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "KZUk_9yIYw0c"
   },
   "outputs": [],
   "source": [
    "@manual{Intro1, \n",
    " title={The Basic Tools of the Deep Life Sciences}, \n",
    " organization={DeepChem},\n",
    " author={Ramsundar, Bharath}, \n",
    " howpublished = {\\url{https://github.com/deepchem/deepchem/blob/master/examples/tutorials/The_Basic_Tools_of_the_Deep_Life_Sciences.ipynb}}, \n",
    " year={2021}, \n",
    "} "
   ]
  }
 ],
 "metadata": {
  "colab": {
   "name": "Copy of 01_The_Basic_Tools_of_the_Deep_Life_Sciences.ipynb",
   "provenance": []
  },
  "kernelspec": {
   "display_name": "deepchem",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.20"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
